﻿using Emgu.CV.CvEnum;
using Emgu.CV;
using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;


namespace August.Core
{
    public class HC
    {
        public static HC Instance = new HC();
        private HTuple modelID;
        public void Imread(string filename, out Image image)
        {
            HObject hObject = null;
            HalconDotNet.HOperatorSet.ReadImage(out hObject, new HTuple(filename));
            image = HObjectToBitmap(hObject);
        }


        public void CreateShapeModel(Image template, HTuple numLevels, HTuple angleStart, HTuple angleExtent, HTuple angleStep, HTuple optimization, HTuple metric, HTuple contrast, HTuple minContrast, out IntPtr modelIntptr)
        {
            HObject hObject = BitmapToHobject(new Bitmap(template));
            HOperatorSet.CreateShapeModel(hObject, numLevels, angleStart, angleExtent, angleStep, optimization, metric, contrast, minContrast, out modelID);
            HHandle intPtrs= modelID.HArr[0];
            IntPtr intPtr = intPtrs.Handle;
            modelIntptr = intPtr;
        }

        public bool FindShapeModel(Image image, IntPtr modelID, HTuple angleStart, HTuple angleExtent, HTuple minScore, HTuple numMatches, HTuple maxOverlap, HTuple subPixel, HTuple numLevels, HTuple greediness, out double row, out double column, out double angle, out double score)
        {
            row = 0d;
            column = 0d;
            angle = 0d;
            score = 0d;
            HObject hObject = BitmapToHobject(new Bitmap(image));
            HHandle hHandle = new HHandle(modelID);
            HTuple id = new HTuple(hHandle);
            HOperatorSet.FindShapeModel(hObject, id, angleStart, angleExtent, minScore, numMatches, maxOverlap, subPixel, numLevels, greediness, out HTuple rowt, out HTuple columnt, out HTuple anglet, out HTuple scoret);
            if(scoret.Length==0)
                return false;
            row = rowt;
            column=columnt;
            angle = anglet;
            score = scoret;
            return true;
        }


        public void CopyRectancleROI(Image src, out Image des,Rectangle rectangle)
        {
            HObject ho_Image = BitmapToHobject(new Bitmap(src));
            rectangle.Width -= rectangle.Width % 4;
            HOperatorSet.GenRectangle1(out HObject ho_Rectangle, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height-1, rectangle.X + rectangle.Width-1);
            HOperatorSet.ReduceDomain(ho_Image, ho_Rectangle, out HObject ho_ImageReduced);
            HOperatorSet.CropDomain(ho_ImageReduced, out HObject ho_ImagePart);
            des = HObjectToBitmap(ho_ImagePart);
        }










        [DllImport("kernel32.dll")]
        public static extern void CopyMemory(int Destination, int add, int Length);
        private Bitmap HObjectToBitmap(HObject ho_Image)
        {
            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
            HOperatorSet.GetImagePointer1(ho_Image, out HTuple  pointer, out HTuple type, out HTuple width, out HTuple height);
            System.Drawing.Imaging.ColorPalette palette = null;
            System.Drawing.Bitmap bitmap = null;
            System.Drawing.Bitmap curBitmap = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
            System.Drawing.Imaging.BitmapData imageData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, curBitmap.PixelFormat);
            //定义用于存储图像数据的Buffer
            byte[] buffer = new byte[imageData.Width * imageData.Height];
            //将图像数据复制到Buffer内
            System.Runtime.InteropServices.Marshal.Copy(pointer, buffer, 0, buffer.Length);
            unsafe
            {
                //使用不安全代码
                fixed (byte* bytePointer = buffer)
                {
                    bitmap = new System.Drawing.Bitmap(imageData.Width, imageData.Height, imageData.Width, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, new IntPtr(bytePointer));
                    palette = bitmap.Palette;
                    for (int Index = 0; Index <= byte.MaxValue; Index++)
                    {
                        palette.Entries[Index] = System.Drawing.Color.FromArgb(byte.MaxValue, Index, Index, Index);
                    }
                    bitmap.Palette = palette;
                }
            }
            return bitmap;
        }


        private HObject BitmapToHobject(Bitmap bitmap)
        {
            BitmapData srcBmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            HOperatorSet.GenImageInterleaved(out HObject hObject, srcBmpData.Scan0, "bgr", bitmap.Width, bitmap.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
            bitmap.UnlockBits(srcBmpData);
            return hObject;
        }
    }
}
